﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WcfServer.Classes.Server;
using WcfServer.Classes.Utility;
using WcfServer.Classes.Client;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using Client.ViewModel;

namespace Client
{
    /// <summary>
    /// Interaction logic for FriendList.xaml
    /// </summary>
    public partial class FriendList : Page
    {
        List<UserSimple> friendslist;

        Socket listener;

        public FriendList()
        {
            InitializeComponent();
        }

        public FriendList(List<WcfServer.Classes.Server.UserSimple> friends,Socket soc)
        {
            InitializeComponent();

            friendslist = friends;

            listener = soc;

            foreach (var i in friends)
            {
                String line = "";
                line += i.FirstName +" "+ i.LastName + " (" + i.UserID+"-" +i.IP + ")" ;
                FriendsList.Items.Add(line);
            }
           
        }

        private void FriendsList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (FriendsList.SelectedIndex == -1)
                return;
            var a = new ServerService.ServerServiceClient();
            var target = friendslist[FriendsList.SelectedIndex];
            if(target.IP == "0.0.0.0")
            {
                //TO ARMAN: show error cannot connect to offline contact.
                return;
            }
            ConnectionRequest cr = new ConnectionRequest()
            {
                srcName = MainWindow.CurrentUserName,
                EncryptedDstName = EncryptionHandler.EncryptAES(SerializerHandler<String>.SerializeInput(target.UserID),MainWindow.ClientServerSessionKey)
            };
            byte[] resp = a.GetConnectionInformation(cr.Send());
            if(resp==null)
            {
                return;
            }
            MainResponse response = new MainResponse( resp );
            UserResponse mine = new UserResponse(response.ClientToken, MainWindow.ClientServerSessionKey);
            //TODO: Validate.

            Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            soc.Connect(IPAddress.Parse(target.IP), target.Port);

            soc.Send(response.TargetToken); //send token.

            byte[] buffer = new byte[1000]; //TODO: is 1KB enough?
            int bytesReceived = soc.Receive(buffer);

            byte[] data = new byte[bytesReceived];
            Buffer.BlockCopy(buffer, 0, data, 0, bytesReceived);

            Ack ack = new Ack(data, mine.SessionKey);
            //TODO: Validate T j = T i + 1 ! using the session key!

            var dialogue = new ChatWindow();
            dialogue.DataContext = new ChatViewModel(soc, mine.SessionKey,mine.SenderID);
            //TODO: THREAD IF REQUIRED!
            dialogue.Show();
        }

        private void Grid_Loaded_1(object sender, RoutedEventArgs e)
        {
            Task.Factory.StartNew( delegate 
            {
                //var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //IPEndPoint ipe = new IPEndPoint(IPAddress.Any, 24200);
                //listener.Bind(ipe);
                listener.Listen(4);
                while (true)
                {
                    var accepted = listener.Accept();
                    Dispatcher.BeginInvoke((Action)(() =>
                    {
                        HandleAccepted(accepted);
                    }));
                }
            });
        }

        public void HandleAccepted(Socket soc)
        {
            byte[] buffer = new byte[10000]; //TODO: is 10KB enough?
            int bytesReceived = soc.Receive(buffer);

            byte[] data = new byte[bytesReceived];
            Buffer.BlockCopy(buffer, 0, data, 0, bytesReceived);

            UserResponse ur = new UserResponse(data, MainWindow.ClientServerSessionKey);

           
            //TODO: Validation?
            Ack ack = new Ack()
            {
                TimeStamp = ur.TimeStamp.AddSeconds(1),//T+1
            };

            byte[] ackToSend = ack.Send(ur.SessionKey);// Ks ( T )
            soc.Send(ackToSend);


            //var dialogue = new ChatWindow(soc, ur.SessionKey);
            var dialogue = new ChatWindow();
            dialogue.DataContext = new ChatViewModel(soc, ur.SessionKey,"");
            dialogue.Show();
           
        }


        private void GoBack(object sender, RoutedEventArgs e)
        {
            this.NavigationService.GoBack();
        }
        
        
    }
}
